# Контексты представлений (contexts)
Имеет смысл отображать [компоненты](/docs/dochub.components) архитектуры в контексте их рассмотрения. Например, если рассматривается
архитектура приложения, нет смысла отображать компоненты сетевой архитектуры на той же схеме.
Разумно разделить эти представления. Контексты позволяют решить эту задачу.

Можно сказать, что контексты реализуют идею [C4 Model](https://ru.wikipedia.org/wiki/%D0%9C%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_C4).
Отличие состоит в том, что контексты не ограничивают вас в количестве уровней представления.

Структура манифеста контекста:
```yaml
contexts:                                   # Контексты представления архитектурных компонентов
    dochub:                                 # Идентификатор контекста
        title: Общая архитектура DocHub     # Название контекста. Отображается в заголовке диаграммы
        location: DocHub/Общая архитектура  # Размещение документа в дереве навигации
        extra-links: false                  # Указывает, что не нужно отображать компоненты явно не указанные в контексте
        components:                         # Компоненты входящие в контекст
            - dochub.front                  # Идентификатор компонента
        uml:                                # PlantUML инъекции
          $before: >                        # Вставляет код ПЕРЕД сгенерированным телом диаграммы
            ...                             
          $after: >                         # Вставляет код ПОСЛЕ сгенерированным телом диаграммы
            ...
        uml: ../docs/sequence.puml          # Ссылка на файл с PlantUML кодом полностью переопределяет представление
```
Чтобы понять это лучше, рассмотрим DocHub в C4 Model:

![](@anchor/c4model_1)

## 1. Уровень I: Система в масштабе ее взаимодействия с пользователями и другими системами

![Система в масштабе ее взаимодействия с пользователями и другими системами](@context/dochub)

Описание контекста в манифесте [/manifest/contexts.yaml](/manifest/contexts.yaml):
```yaml
contexts:  
    dochub:                                 # Идентификатор контекста
        title: Общая архитектура DocHub     # Название контекста
        location: DocHub                    # Размещение документа в дереве навигации
        components:                         # Компоненты входящие в контекст
            - dochub.front
            - dochub.user
            - dochub.plantuml
            - dochub.gitlab
            - dochub.web
    ...
```
Это простейшее описание контекста. По сути, контекст описывает какие компоненты будут отображаться на схеме,
под каким названием и где пользователь сможет найти контекст в навигационном меню. Связи между компонентами описаны
в самих компонентах (см. [компоненты](/docs/dochub.components)).

Обратите внимание, что внизу компонента "DocHub" есть символы ">>". Кликнув по ним, вы "провалитесь" внутрь компонента.

![](@anchor/c4model_2)

## 2. Уровень II: Взаимосвязанные контейнеры
![Взаимосвязанные контейнеры](@context/dochub.front)

Описание контекста в манифесте [/manifest/contexts.yaml](/manifest/contexts.yaml):
```yaml
contexts:   # Контексты представления архитектурных компонентов
    ...
    dochub.front:
        title: Контейнерная архитектура DocHub
        location: DocHub/Контейнерная архитектура
        components:
            - dochub.browser.localstorage
            - dochub.front.spa
            - dochub.gitlab.api
            - dochub.gitlab.oauth
            - dochub.gitlab.repository
            - dochub.gitlab.gitclient
            - dochub.plantuml.jar
            - dochub.web
    ...
```
![](@anchor/c4model_3)

## 3. Уровень III: Взаимосвязанные компоненты
![Взаимосвязанные компоненты](@context/dochub.front.spa)

Описание контекста в манифесте [/manifest/contexts.yaml](/manifest/contexts.yaml):
```yaml
contexts:   # Контексты представления архитектурных компонентов
    ...
    dochub.front.spa:
        title: Компонентная архитектура DocHub
        location: DocHub/Компонентная архитектура
        components:
            - dochub.front.spa.*
    ...
```

Обратите внимение, что компоненты в контекст можно включать по маске.
Звездочка в конце предполагает включение всех компонентов этого уровня в контекст.

Также, допустимой маской является такая запись:

```
    dochub.*.spa.*
```

Если указывается двойная звездочка, то отбираются все компоненты текущего и нижележащих уровней.

Например, так:

```
    dochub.**
```

## 4. Уровень IV: дополнительные сведения о дизайне архитектурных элементов
![дополнительные сведения о дизайне архитектурных элементов](@context/dochub.sequence)

Описание контекста в манифесте [/manifest/contexts.yaml](/manifest/contexts.yaml):
```yaml
contexts:   # Контексты представления архитектурных компонентов
    ...
    dochub.sequence:
        title: Диаграмма взаимодействия DocHub
        location: DocHub/Диаграмма взаимодействия
        presentation: plantuml      # Явно определяет используемую презентацию контекста
        uml: ../docs/sequence.puml  # Ссылка на файл с кодом PlantUML
    ...
```
Стандартным методом представления контекстов является автоматическая генерация PlantUML кода на основании манифеста
контекста, где перечисленны компоненты. Компоненты содержат достаточную информацию для построения диаграммы связей.
Но в некоторых случаях, нет необходимости в таком подходе. Например, если необходимо описать диаграмму взаимодействия
(как здесь). Другим примером может стать концептуальное проектирование. В этом случае до утверждения схемы,
нет необходимости генерировать манифесты компонентов.

Контексты позволяют переопределить представление на PlantUML код. В этом случае в поле "uml" указывается ссылка на
файл, содержащий код.

## 5. Источник данных для контекста
По умочанию, источником данных для контекста является весь код архитектуры. На этот источник накладывается 
фильтр, параметры для которого указываются в манифесте контекста. Например, в поле "components" определяются
какие компоненты должны отображаться.

Но есть возможность до того, как будет применен фильтр, преобразовать данные. Для этого необходимо 
переопределить источник. Сделать это можно используя поля "source" и "original", аналогично [таблицам](/docs/dochub.tables).

```yaml
    ...
    dochub.custom:
        title: Компоненты эксперта R.Piontik
        location: DocHub/Контекст по источнику
        extra-links: false  # Отключаем вывод связанных компонентов, явно не определенных в контексте
                            # Определяем источник данных для контекста.
        source: >           # Отбираем все компоненты у которых кастомное поле "expert" = "R.Piontik"
            (               
                $ ~> | $ | {
                    "components": $merge(components.$spread().(
                        $.*.expert = 'R.Piontik' ? $ : {}
                    )) 
                } |
            )
        components:
            - dochub.*      # Выводим все компоненты домена dochub
    ...
```

В данном примере код архитектуры перобразуется с целью выбора компонентов, экспертом по которым является R.Piontik. 
Поведение будет таким:

![Источник данных контекста](@document/dochub.context.source)


Фильтр по компонентам будет применятся уже к подготовленным данным источником. 
Результат:

![Компоненты в которых эксперт R.Piontik](@context/dochub.custom)

